/*
 
 RFA Manager, Refractor2 Archive editor.
 Copyright (C) 2008
 Torsten Kammer         torsten@ferroequinologist.de
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 */

#import "OutlineViewDelegate.h"
#import "MyDocument.h"
#import "ImageAndTextCell.h"
#import "RFATreeNode.h"
#import "RFAArchive.h"
#import "RFABrowserCell.h"

static NSString *RFATreeNodeReferencePboardType = @"com.googlecode.bmmt.rfamanager.treenodereferencetype";

@interface OutlineViewDelegate ()

- (NSArray *)_namesForFiles:(NSArray *)items createdAt:(NSString *)path;

- (BOOL)_writeNodes:(NSArray *)items toPasteboard:(NSPasteboard *)pboard;

@end

@implementation OutlineViewDelegate

- (id)initWithDocument:(MyDocument *)aDocument;
{
    if (![super init]) return nil;
    
    self.document = aDocument;
    
    document.outlineView.dataSource = self;
	[document.outlineView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
	[document.outlineView setDraggingSourceOperationMask:NSDragOperationNone forLocal:YES];
	
	document.browser.delegate = self;
	[document.browser setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
	[document.browser setDraggingSourceOperationMask:NSDragOperationNone forLocal:YES];
    
	document.searchView.dataSource = self;
	[document.searchView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
	[document.searchView setDraggingSourceOperationMask:NSDragOperationNone forLocal:YES];
	
    return self;
}

@synthesize document;

#pragma mark -

- (NSArray *)outlineView:(NSOutlineView *)outlineView namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination forDraggedItems:(NSArray *)items
{
	return [self _namesForFiles:[items valueForKey:@"representedObject"] createdAt:dropDestination.path];
}

- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
{
    return [self _writeNodes:[items valueForKey:@"representedObject"] toPasteboard:pboard];
}

#pragma mark -

- (NSArray *)browser:(NSBrowser *)sender namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)columnIndex
{
	// Get the elements
	NSMatrix *matrix = [sender matrixInColumn:columnIndex];
	
	NSMutableArray *items = [NSMutableArray array];
	
	NSUInteger index = rowIndexes.firstIndex;
	do
	{
		RFABrowserCell *cell = [matrix cellAtRow:index column:0];
		[items addObject:cell.objectValue];
	}
	while ((index = [rowIndexes indexGreaterThanIndex:index]) != NSNotFound);
	
	return [self _namesForFiles:items createdAt:dropDestination.path];
}

- (BOOL)browser:(NSBrowser *)sender canDragRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)columnIndex withEvent:(NSEvent *)dragEvent
{
	return YES;
}

- (BOOL)browser:(NSBrowser *)sender writeRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)columnIndex toPasteboard:(NSPasteboard *)pasteboard
{
	// Get the elements
	NSMatrix *matrix = [sender matrixInColumn:columnIndex];
	
	NSMutableArray *items = [NSMutableArray array];
	
	NSUInteger index = rowIndexes.firstIndex;
	do
	{
		RFABrowserCell *cell = [matrix cellAtRow:index column:0];
		[items addObject:cell.objectValue];
	}
	while ((index = [rowIndexes indexGreaterThanIndex:index]) != NSNotFound);
	
	return [self _writeNodes:items toPasteboard:pasteboard];
}

- (void)browser:(NSBrowser *)sender willDisplayCell:(id)cell atRow:(NSInteger)row column:(NSInteger)column
{
	// Has to be implemented, though we don't do anything here.
}

#pragma mark -

- (NSArray *)tableView:(NSTableView *)aTableView namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes
{	
	// Warning: Using self as the key to get the represented object is a hack and may stop working in future releases.
	return [self _namesForFiles:[[document.searchArrayController.arrangedObjects objectsAtIndexes:rowIndexes] valueForKey:@"self"] createdAt:dropDestination.path];
}

- (BOOL)tableView:(NSTableView *)aTableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard
{
	// Warning: Using self as the key to get the represented object is a hack and may stop working in future releases.
	return [self _writeNodes:[[document.searchArrayController.arrangedObjects objectsAtIndexes:rowIndexes] valueForKey:@"self"] toPasteboard:pboard];
}

#pragma mark -

- (BOOL)_writeNodes:(NSArray *)items toPasteboard:(NSPasteboard *)pboard;
{
	if (items.count == 1)
    {
        RFATreeNode *node = [items objectAtIndex:0];
        NSMutableArray *declaredPboardTypes = [NSMutableArray arrayWithObjects:NSFilesPromisePboardType, nil];
        if ([[RFAArchiveEntry extensionsToTreatAsText] containsObject:node.path.pathExtension])
            [declaredPboardTypes addObject:NSStringPboardType];
        else if ([[RFAArchiveEntry extensionsToTreatAsImage] containsObject:node.path.pathExtension])
            [declaredPboardTypes addObject:NSTIFFPboardType];
        
        [pboard declareTypes:declaredPboardTypes owner:self];
        
        //[pboard setPropertyList:[NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:[self.document fileURL], @"fileURL", [NSArray arrayWithObject:node.path], @"filePath", nil]] forType:RFATreeNodeReferencePboardType];
		if ([node isKindOfClass:[RFAArchiveEntry class]] || node.isLeaf)
			[pboard setPropertyList:[NSArray arrayWithObject:node.path.pathExtension] forType:NSFilesPromisePboardType];
		else
			[pboard setPropertyList:[NSArray arrayWithObject:NSFileTypeDirectory] forType:NSFilesPromisePboardType];
			
        if ([[RFAArchiveEntry extensionsToTreatAsText] containsObject:node.path.pathExtension])
            [pboard setString:node.contents forType:NSStringPboardType];
		else if ([[RFAArchiveEntry extensionsToTreatAsImage] containsObject:node.path.pathExtension])
			[pboard setData:node.image.TIFFRepresentation forType:NSTIFFPboardType];
    }
    else
    {
        [pboard declareTypes:[NSArray arrayWithObjects:NSFilesPromisePboardType, nil] owner:self];
        
		NSMutableArray *extensions = [NSMutableArray array];
		for (RFATreeNode *node in items)
		{
			NSString *type = nil;
			if ([node isKindOfClass:[RFAArchiveEntry class]] || node.isLeaf)
				type = node.path.pathExtension;
			else
				type = NSFileTypeDirectory;
				
			if (![extensions containsObject:type])
				[extensions addObject:type];
		}
				
		[pboard setPropertyList:extensions forType:NSFilesPromisePboardType];
    }
    return YES;
}

- (NSArray *)_namesForFiles:(NSArray *)items createdAt:(NSString *)path;
{
	NSMutableArray *result = [NSMutableArray array];
	for (RFATreeNode *node in items)
	{
		NSString *pathName = [path stringByAppendingPathComponent:node.path.lastPathComponent];
		if ([node isKindOfClass:[RFAArchiveEntry class]] || node.isLeaf)
		{
			[result addObject:pathName];
			[node.data writeToFile:pathName atomically:YES];
		}
		else
		{
			BOOL isDir;
			if (![[NSFileManager defaultManager] fileExistsAtPath:pathName isDirectory:&isDir])
			{
				[[NSFileManager defaultManager] createDirectoryAtPath:pathName withIntermediateDirectories:NO attributes:nil error:nil];
			}
			[result addObjectsFromArray:[self _namesForFiles:node.children createdAt:pathName]];
		}
	}
	
	return result;
}

@end
